using System;
using System.Linq;
using System.Collections.Generic;
using System.Security.Principal;
using JSC.Portal.Entities.Interfaces;

namespace JSC.Portal.Entities
{
	public partial class Section : DescriptiveEntity, ITracked, IValid, IMovable
	{
        /// <summary>
        /// Can anonymous visitors view the content of this section?
        /// </summary>
        public virtual bool AnonymousViewAllowed
        {
            get { return (SectionPermissions.Count(sp => sp.Role.RoleEnum == Roles.Anonymous) > 0); }
        }

        public bool EditAllowed(Role role)
		{
			return EditAllowed(role.RoleEnum);
		}

		public bool EditAllowed(Roles role)
		{
            return (SectionPermissions.Count(sp => sp.Role.RoleEnum == role) > 0);
		}

        /// <summary>
        /// Indicates if viewing of the section is allowed. Anonymous users get a special treatment because we
        /// can't check their rights because they are no full-blown Portal users (not authenticated).
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public virtual bool ViewAllowed(IIdentity user)
        {
            PortalUser portaluser = user as PortalUser;
            if (AnonymousViewAllowed)
            {
                return true;
            }
            else if (portaluser != null)
            {
                return portaluser.CanView(this);
            }
            else
            {
                return false;
            }
        }

		public bool ViewAllowed(Role role)
		{
			return ViewAllowed(role.RoleEnum);
		}

		public bool ViewAllowed(Roles role)
		{
            return (SectionPermissions.Count(sp => sp.ViewAllowed && sp.Role.RoleEnum == role) > 0);
		}

		/// <summary>
		/// Copy permissions from the parent Node
		/// </summary>
		public virtual void CopyRolesFromPortalPage()
		{
			if (Page != null)
			{
				foreach (PortalPagePermission ppp in Page.PagePermissions)
				{
					SectionPermission sp = new SectionPermission();
					sp.Section = this;
					sp.Role = ppp.Role;
					sp.ViewAllowed = ppp.ViewAllowed;
					sp.EditAllowed = ppp.EditAllowed;
					SectionPermissions.Add(sp);
				}
			}
		}

		public SectionPermission GetPermission(Role role)
		{
            return GetPermission(role.RoleEnum);
        }

		public SectionPermission GetPermission(Roles role)
		{
            return SectionPermissions.SingleOrDefault(sp => sp.Role.RoleEnum == role);
		}

        public bool TryGetSectionModulePropertyValue(string propertyName, out string value)
        {
            bool result = false;
            value = null;
            SectionModulePropertyValue val = Settings.SingleOrDefault(s => s.ModuleProperty.Name == propertyName);
            if (val != null)
            {
                value = val.Value;
                result = true;
            }
            return result;
        }

        #region IMovable Members

        public bool CanMove()
        {
            return !IsNew && (CanMoveDown() || CanMoveUp());
        }

        public bool CanMoveUp()
        {
            if (!IsNew && this.Page != null)
            {
                int min =
                    (
                        from section in this.Page.Sections
                        where section.Placeholder == this.Placeholder
                        select section
                    ).Min(m => m.Position);
                return (this.Position > min);
            }
            return false;
        }

        public bool CanMoveDown()
        {
            if (!IsNew && this.Page != null)
            {
                int max =
                    (
                        from section in this.Page.Sections
                        where section.Placeholder == this.Placeholder
                        select section
                    ).Max(m => m.Position);
                return (this.Position < max);
            }
            return false;
        }

        public bool CanMoveLeft()
        {
            return false;
        }

        public bool CanMoveRight()
        {
            return false;
        }

        #endregion
    }
}
